package com.ybear.ybhotrepair.core;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.ybear.ybhotrepair.BaseReqBuild;
import com.ybear.ybhotrepair.utils.IOUtil;

/**
 * 热修复管理器
 *
 * 文件校验：SHA256
 */
public class HotRepairManage {
    private Application mContext;
    private RequestManage mReq;
    private DexImpl mDexImpl;

    private HotRepairManage() {}
    public static HotRepairManage getInstance() {
        return HANDLER.INSTANCE;
    }
    private static final class HANDLER {
        private static final HotRepairManage INSTANCE = new HotRepairManage();
    }

    public HotRepairManage init(@NonNull Application application) {
        mContext = application;
        mReq = new RequestManage( mContext );
        mDexImpl = new DexImpl( mContext, mReq );
        return this;
    }

    /**
     * 简单的请求
     * @param url   服务器地址
     * @return      this
     */
    public HotRepairManage setSimpleReq(String url) {
        mReq.setServerUrl( url );
        return this;
    }

    /**
     * 完整的构建请求
     * @param build     构建请求
     * @param <T>       泛型
     * @return          this
     */
    public <T extends BaseReqBuild> HotRepairManage setBuildReq(T build) {
        mReq.setReqBuild( build );
        return this;
    }

    /**
     * 开始修复
     * 从本地读取补丁版本，不存在时从后台下载dex文件，否则直接从本地加载。
     * 后台下载完成的dex文件不会立刻修复，而是下次启动App时通过本地加载dex文件进行修复
     * @param token     后台可能需要的token，不需要设为null
     */
    public void startRepair(String token) {
        mReq.setToken( token );

        String dexVer = checkDexVer();
        //本地不存在版本号 或者 修复文件
        if( dexVer == null ) {
            //请求下载dex文件
            mDexImpl.reqDwonloadDexFile();
        }else {
            //开始修复检查（防止后台再次对当前版本更新）
            mDexImpl.reqCheckRepair();
            //从本地加载修复的dex文件
            mDexImpl.loadRepairDexFile( dexVer );
        }
    }
    public void startRepair() {
        startRepair( null );
    }

    /**
     * 检查dex版本
     * @return  版本号，返回null时验证失败
     */
    @Nullable
    private String checkDexVer() {
        String ver = IOUtil.readDexVersion( mContext );
        return ver == null || mDexImpl.getLocalDexFileCount() == 0 ? null : ver;
    }
}
